package com.zyh.cxf;

import com.zyh.dao.KeyMapper;
import com.zyh.dao.TrandMapper;
import com.zyh.pojo.Zjywpt_yg_trand_infos;
import com.zyh.service.BaseService;
import com.zyh.util.*;

import com.zyh.util.ESBQRCB01.*;
import com.zyh.util.ESBQRCB02.ESBErrorQRCBBody02;
import com.zyh.util.ESBQRCB02.ESBQRCBHead02;
import com.zyh.util.ESBQRCB02.EsbErrorResponseQRCB02;
import com.zyh.util.ESBQRCB02.EsbResponseQRCB02;
import com.zyh.util.safeutil.DESedeUtil;
import com.zyh.util.safeutil.SM2Utils;
import com.zyh.util.safeutil.Util;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author shihan
 * @date 2020-12-04-14:00
 */
@Component
public class GetAccountBalanceDesImpl implements GetAccountBalanceDes, BaseService {

    @Autowired
    private TrandMapper trandMapper;
    public static GetAccountBalanceDesImpl getAccountBalanceDes;
    @Autowired
    private KeyMapper keyMapper;
    @Override
    public int deCode() {
        return 0;
    }

    @Override
    public int check() {
        return 0;
    }

    @Override
    public int initi() {
        return 0;
    }

    @PostConstruct
    public void init() {

        getAccountBalanceDes = this;
        getAccountBalanceDes.trandMapper = this.trandMapper;
    }

    @Override
    public int doBusiness() {
        return 0;
    }

    @Override
    public int doPage() {
        return 0;
    }

    @Override
    public int enCode() {
        return 0;
    }

    public static void addGetAcc(Zjywpt_yg_trand_infos zjywpt_yg_trand_infos) {

        getAccountBalanceDes.trandMapper.addTrand(zjywpt_yg_trand_infos);
    }

    @Override
    public String getABalanceDes(String xmlData) {

        Map<String, Object> keyMap = keyMapper.querykey();
        //查询加密的公钥
        String inencryptKey=(String)keyMap.get("PublicKey");
        String privateKey=(String)keyMap.get("PrivateKey");
        //第一步密钥解密
        System.err.println("密钥sm2私钥解密：");
        String plainText = null;
        try {
            plainText = new String(SM2Utils.decrypt(Util.hexToByte(privateKey), Util.hexToByte(inencryptKey)));
        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println("密钥明文：" + plainText);
        // 第二步通过拿到的解密密钥进行报文解密
        String inresource = null;
        try {
            inresource = DESedeUtil.decrypt(xmlData, plainText);
        } catch (Exception e) {
            e.printStackTrace();
        }

        System.out.println("医保端明文："+ inresource);

        //落库记录表对象
        Zjywpt_yg_trand_infos zjywpt_yg_trand_infos = new Zjywpt_yg_trand_infos();
        //交易日期
        String RECDATE = RandomNumber.productTxnDt();
        //交易时间
        String RETDATE = RandomNumber.productTxnTm();
        zjywpt_yg_trand_infos.setRECDATE(RECDATE);
        zjywpt_yg_trand_infos.setRETDATE(RETDATE);
        // 全局流水号
        String ESBID = RandomNumber.productBsnSrNo();

        //用于接收 医保端“查询余额请求”的账号字段-PayerAcNO

        Map<String, String> mapQRC01 = doRequestObj(inresource);
        String PayerAcNO = mapQRC01.get("PayerAcNo");
        String serialNo = mapQRC01.get("serialNo");
        String EndDate = mapQRC01.get("EndDate");

        String BeginDate = mapQRC01.get("BeginDate");

        if(BeginDate.length() != 8 || EndDate.length() != 8){

            //返回错误响应


            return  errorXml(ESBID,"000","请求时间格式不对",plainText);
        }

        if(PayerAcNO.matches(".*[A-Za-z]+.*") || PayerAcNO.length() != 17){

            //返回错误响应
            return  errorXml(ESBID,"000","请求账户不合法,应为17位数字",plainText);

        }
        String   mainAccNo = this.trandMapper.queryAccNoById(PayerAcNO);


        if(mainAccNo == null){

            //返回错误响应
            return  errorXml(ESBID,"000","该账户不在本行系统中，请再次核对",plainText);
        }

        //解析请求，获得请求具体行为【拼接为ESB的请求】
        String xmlESBRequest = getXmlInfo23T(ESBID, PayerAcNO, BeginDate, EndDate);//


        //模拟获得对象
        //拼接请求参数行为， 调用Socket发送 【XML】
        String xmlESBResponse = SocketUtils.sendData(xmlESBRequest);
        // 获得ESB返回参数，解析成对象
        //通过返回码 假定 RetCd=000000 为正常报文
        EsbResponseQRCB02 esbResponseQRCB02 = null;
        ESBQRCBHead02 esbqrcbHead02 = null;
        String responseToYBxml = null;
        String IBSJnlNo ="";
        String returnCode = "";
        String ESBMSG  = "";
        if(xmlESBResponse.length() > 0){
        try {
            esbResponseQRCB02 = Dom23.doESBResponseObj02(xmlESBResponse, serialNo);

             ESBMSG  = esbResponseQRCB02.getEsbqrcbHead02().getIBSReturnMsg();
            esbqrcbHead02 = esbResponseQRCB02.getEsbqrcbHead02();
            IBSJnlNo = esbqrcbHead02.getIBSJnlNo();
            if("服务识别失败".equals(ESBMSG)){

                return "error: " + "服务识别失败";

            }
            responseToYBxml = XstreamKit.vo2Xml(esbResponseQRCB02);

             returnCode = esbResponseQRCB02.getEsbqrcbHead02().getIBSReturnCode();


            zjywpt_yg_trand_infos.setESBMSG(ESBMSG);
            zjywpt_yg_trand_infos.setESBID(ESBID);
            zjywpt_yg_trand_infos.setESBSTATUS(esbqrcbHead02.getIBSReturnCode());

            zjywpt_yg_trand_infos.setESBServiceCode("30013000123");
            zjywpt_yg_trand_infos.setESBOUT(xmlESBResponse);
            zjywpt_yg_trand_infos.setESBIN(xmlESBRequest);

            zjywpt_yg_trand_infos.setYBIN(inresource);
            zjywpt_yg_trand_infos.setYBOUT(responseToYBxml);

            //加密发送给医保端
            try {
                responseToYBxml = DESedeUtil.encrypt(responseToYBxml, plainText);
            } catch (Exception e) {
                e.printStackTrace();
            }

            zjywpt_yg_trand_infos.setCreator("");
            zjywpt_yg_trand_infos.setCreationtime("");
            zjywpt_yg_trand_infos.setModifier("");
            zjywpt_yg_trand_infos.setModifiedtime("");
            zjywpt_yg_trand_infos.setINTERFACENO("QRCB002");

            //ESB 成功后返回代码为 000000
            if ("000000".equals(returnCode)) {

                zjywpt_yg_trand_infos.setSTATUS("90");
                zjywpt_yg_trand_infos.setESBMSG("交易明细查询成功");
                addGetAcc(zjywpt_yg_trand_infos);


            } else {
                zjywpt_yg_trand_infos.setSTATUS("91");
                zjywpt_yg_trand_infos.setESBMSG("交易名称查询失败");

                responseToYBxml = errorXml(IBSJnlNo,returnCode,ESBMSG,plainText);


                addGetAcc(zjywpt_yg_trand_infos);


                return responseToYBxml;
            }

        } catch (DocumentException e) {
            e.printStackTrace();
        }}else{

            return errorXml(IBSJnlNo,returnCode,ESBMSG,"error: " + "ESB系统繁忙，请稍后再试");
        }


        return responseToYBxml;


    }


    //解析医保端请求方的XML数据
    private Map<String, String> doRequestObj(String xmlData) {

        Map<String, String> mapQRC01 = new HashMap<>();
        Document doc = null;
        try {
            doc = DocumentHelper.parseText(xmlData);
            Element rootElt = doc.getRootElement();

            // 只返回 Head 内容
            Iterator itersHead = rootElt.elementIterator("Head");

            while (itersHead.hasNext()) {

                Element reEless = (Element) itersHead.next();
                String serialNo = reEless.elementTextTrim("serialNo");
                String reqTime = reEless.elementTextTrim("reqTime");

                mapQRC01.put("serialNo", serialNo);
                mapQRC01.put("reqTime", reqTime);

            }

            // 只返回 Body 内容
            Iterator itersBody = rootElt.elementIterator("Body");
            while (itersBody.hasNext()) {

                Element reEless = (Element) itersBody.next();
                //账户流水查询用账户号【解析传入】
                String PayerAcNO = reEless.elementTextTrim("PayerAcNo");
                String BeginDate = reEless.elementTextTrim("BeginDate");
                String EndDate = reEless.elementTextTrim("EndDate");

                String PayerCurrency = reEless.elementTextTrim("PayerCurrency");

                mapQRC01.put("PayerAcNo", PayerAcNO);
                mapQRC01.put("PayerCurrency", PayerCurrency);

                mapQRC01.put("BeginDate", BeginDate);
                mapQRC01.put("EndDate", EndDate);

            }


        } catch (DocumentException e) {
            System.out.println(e.getMessage());
        }

        return mapQRC01;
    }

    //生成xml格式数据 23
    public String getXmlInfo23T(String uuid, String PayerAcNO, String BeginDate, String EndDate) {

        Document doc = DocumentHelper.createDocument();

        Element service = doc.addElement("service");
        Element SysHead = service.addElement("SysHead");
        Element AppHead = service.addElement("AppHead");
        Element LocalHead = service.addElement("LocalHead");
        Element Body = service.addElement("Body");

        Element SvcCd = SysHead.addElement("SvcCd");
        Element ScnCd = SysHead.addElement("ScnCd");
        Element CnsmrSysNo = SysHead.addElement("CnsmrSysNo");
        Element BsnSrlNo = SysHead.addElement("BsnSrlNo");
        Element TxnDt = SysHead.addElement("TxnDt");
        Element TxnTm = SysHead.addElement("TxnTm");

        SvcCd.setText("300130001");
        ScnCd.setText("23");//历史交易流水查询
        CnsmrSysNo.setText(ConfigInfo.getConfigInfoByName("esb.CnsmrSysNo"));//消费方ID
        BsnSrlNo.setText(uuid);//每次不一样

        TxnDt.setText(RandomNumber.productTxnDt());
        TxnTm.setText(RandomNumber.productTxnTm());

        Element CnlCd = AppHead.addElement("CnlCd");
        Element InstNo = AppHead.addElement("InstNo");
        Element OtltsNo = AppHead.addElement("OtltsNo");
        Element UsrNo = AppHead.addElement("UsrNo");


        CnlCd.setText(ConfigInfo.getConfigInfoByName("esb.cnlCd"));
        InstNo.setText("003");
        OtltsNo.setText("10001");
        UsrNo.setText("8170004");


        Element TlrTp = LocalHead.addElement("TlrTp");
        Element AuthTlrNo = LocalHead.addElement("AuthTlrNo");
        Element OldAcctFlg = LocalHead.addElement("OldAcctFlg");


        TlrTp.setText("0");
        AuthTlrNo.setText("0000000");
        OldAcctFlg.setText("1");


        // request args must reset value

        Element ProvCd = Body.addElement("ProvCd");//省代码
        Element OldAcctNo = Body.addElement("OldAcctNo");//旧帐号
        Element OldAcctOfstLo = Body.addElement("OldAcctOfstLo");//旧账号偏移位置
        Element AcctNo = Body.addElement("AcctNo");//账号
        Element SubAcctCtgry = Body.addElement("SubAcctCtgry");//子账户类别
        Element SubAcctVlmNo = Body.addElement("SubAcctVlmNo");//子账号册号
        Element SubAcctSeqNo = Body.addElement("SubAcctSeqNo");//子账号序号
        Element TxnBegDt = Body.addElement("TxnBegDt");//交易开始时间
        Element TxnEndDt = Body.addElement("TxnEndDt");//交易介绍时间


        ProvCd.setText("43");//默认
        // OldAcctNo.setText("");
        OldAcctOfstLo.setText("29");
        AcctNo.setText(PayerAcNO);
        //   SubAcctCtgry.setText("T");
        ////  SubAcctVlmNo.setText("0");
        SubAcctSeqNo.setText("0");
        // 倒序日期  公共类


        String byyyy = BeginDate.substring(0, 4);//2020
        String bMM = BeginDate.substring(4, 6);
        String bdd = BeginDate.substring(6, 8);
        String eyyyy = EndDate.substring(0, 4);//2020
        String eMM = EndDate.substring(4, 6);
        String edd = EndDate.substring(6, 8);
        TxnBegDt.setText(bdd + bMM + byyyy);
        TxnEndDt.setText(edd + eMM + eyyyy);


        String docData = doc.asXML();
        byte[] bytes = docData.getBytes();


        return doc.asXML();
    }


    public String errorXml(String IBSJnlNo,String returnCode,String ESBMSG,String key){

        EsbErrorResponseQRCB02 esbErrorResponseQRCB02 = new EsbErrorResponseQRCB02();
        ESBQRCBHead02 esbqrcbHead2 = new ESBQRCBHead02();
        esbqrcbHead2.setIBSJnlNo(IBSJnlNo);
        esbqrcbHead2.setIBSReturnCode(returnCode);
        esbqrcbHead2.setIBSReturnMsg(ESBMSG);
        esbErrorResponseQRCB02.setEsbqrcbHead02(esbqrcbHead2);

        ESBErrorQRCBBody02 esbErrorQRCBBody02 = new ESBErrorQRCBBody02();
        esbErrorQRCBBody02.setOrderState("91");
        esbErrorQRCBBody02.setOrderFlowDescript(ESBMSG);
        esbErrorResponseQRCB02.setEsbErrorQRCBBody02(esbErrorQRCBBody02);

        String errorXml  = XstreamKit.vo2Xml(esbErrorResponseQRCB02);
        //加密发送给医保端
        try {
            errorXml = DESedeUtil.encrypt(errorXml, key);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return errorXml;
    }

}
